#include <iostream>
#include <vector>
#include <cstring>

#include "HttpServer/httpserver.hpp"
#include "server.hpp"
#include <fstream>

size_t Split(const std::string &src, const std::string &sep, std::vector<std::string> *array) // 字符串分割
{
    std::string src_cp = src;
    std::string sep_cp = sep;
    char *pos = NULL;
    pos = strtok(&src_cp[0], &sep_cp[0]);
    while (pos != NULL)
    {
        array->push_back(pos);
        pos = strtok(NULL, &sep_cp[0]);
    }
    return array->size();
}

void t_Split()
{
    std::vector<std::string> strs;
    std::string s = "aadss: adas\r\n";
    // std::string s = "a,bds,dsa.daaf;;";
    std::string sep = ": ";
    size_t num = Split(s, sep, &strs);
    std::cout << num << std::endl;
    for (auto &s : strs)
    {
        std::cout << "[" << s << "]" << " ";
    }
    std::cout << std::endl;
}

static bool ReadFile(const std::string &filename, Buffer *buf) // 读取文件所有内容放到 Buffer 中
{
    std::ifstream ifs(filename, std::ios::binary); // 二进制形式读取文件
    if (ifs.is_open() == false)
    {
        ERROR_LOG("open %s file failed !", filename);
        return false;
    }

    size_t filesize = 0;
    ifs.seekg(0, ifs.end);
    filesize = ifs.tellg(); // 获取文件大小
    ifs.seekg(0, ifs.beg);

    std::string str;
    str.resize(filesize);
    ifs.read(&str[0], filesize); // 读取流正常
    if (ifs.good() == false)     // 检查流正常
    {
        ERROR_LOG("Read %s File Failed !", filename.c_str());
        ifs.close();
        return false;
    }
    buf->WriteString(str); // 写入buf
    return true;
}

void t_ReadFile()
{
    Buffer buf;
    ReadFile("./timewheel.hpp", &buf);
    // std::cout << buf.ReadAsString(buf.ReadableSize()) << std::endl;
    std::cout << buf.ReadPos() << std::endl;
}

static std::string UrlEncode(const std::string url, bool convert_space2plus) // URL编码
{
    std::string res;
    for (auto &c : url)
    {
        if (c == '.' || c == '-' || c == '_' || c == '~' || isalnum(c)) // isalnum 判断是否为字母和数字
        {
            res += c;
            continue;
        }
        if (c == ' ' && convert_space2plus)
        {
            res += '+';
            continue;
        }

        // 剩下字符都要编码
        char tmp[4] = {0};
        snprintf(tmp, sizeof(tmp), "%%%02X", c);
        res += tmp;
    }
    return res;
}

std::string t_UrlEncode()
{
    std::string src = "/login?pwd=C++&Cpp  ";
    std::cout << "src: " << '[' << src << ']' << std::endl;
    std::string res = UrlEncode(src, true);
    std::cout << "UrlEncode(src, true): " << '[' << res << ']' << std::endl;
    return res;
}

static char HexToI(char c)
{
    if (c >= '0' && c <= '9')
    {
        return c - '0';
    }
    if (c >= 'a' && c <= 'z')
    {
        return c - 'a' + 10;
    }
    if (c >= 'A' && c <= 'Z')
    {
        return c - 'A' + 10;
    }
    return -1;
}

static std::string UrlDecode(const std::string url, bool convert_plus2space) // URL解码
{
    std::string res;
    // 遇到 %，将其后的2个字符，转换为数字，第一个数字左移4位（等价于 *16），然后加上第二个数字
    for (int i = 0; i < url.size(); i++)
    {
        if (url[i] == '%')
        {
            char v1 = HexToI(url[i + 1]);
            char v2 = HexToI(url[i + 2]);
            char v = (v1 << 4) + v2;
            res += v;
            i += 2;
        }
        else if (url[i] == '+' && convert_plus2space)
        {
            res += ' ';
        }
        else
        {
            res += url[i];
        }
    }
    return res;
}

void t_UrlDecode(const std::string &str)
{
    std::string res = UrlDecode(str, true);
    std::cout << "UrlDecode(str, true): " << '[' << res << ']' << std::endl;
}


static bool IsDir(const std::string &filename)     // 判断文件是否为目录
    {
        struct stat st;
        int ret = stat(filename.c_str(), &st);      // 获取文件属性
        if(ret < 0)
        {
            ERROR_LOG("Util::static bool IsDir  Failed !");
            return false;
        }
        return S_ISDIR(st.st_mode);     // 直接用 stat 中的宏就可以
    }

static bool IsRegular(const std::string &filename)     // 判断是否为普通文件
{
    struct stat st;
    int ret = stat(filename.c_str(), &st);      // 获取文件属性
    if(ret < 0)
    {
        ERROR_LOG("Util::static bool IsRegular  Failed !");
        return false;
    }
    return S_ISREG(st.st_mode);     // 直接用 stat 中的宏就可以
}

void t_IsDir_IsRegular()
{
    std::cout << "IsDir(\"test\"): " << IsDir("test") << std::endl;
    std::cout << "IsDir(\"prac\"): " << IsDir("prac") << std::endl;
    std::cout << "IsRegular(\"test\"): " << IsRegular("test") << std::endl;
    std::cout << "IsRegular(\"prac\"): " << IsRegular("prac") << std::endl;
}

static bool ValidPath(const std::string &path)     // 请求的资源路径的有效性判断
{
    std::vector<std::string> subdir;
    Split(path, "/", &subdir);

    for(auto &dir : subdir)
    {
        std::cout << "[" << dir << "]" << " ";
    }
    std::cout << std::endl;

    int level = 0;      // 初始目录深度
    for(auto &d : subdir)
    {
        if(d == "..")
        {
            level--;
            if(level < 0)
            {
                return false;
            }
        }
        else
        {
            level++;
        }
    }
    return level > 0;
}

void t_ValidPath()
{
    // std::string path = "/index.html/../../aaa";
    std::string path = "/";
    bool ret = ValidPath(path);
    std::cout << path << " is " << ret << std::endl; 
}

int main()
{
    
    // t_UrlDecode(t_UrlEncode());
    // t_IsDir_IsRegular();
    // t_ValidPath();
    t_Split();
    

    return 0;
}